package com.smartEdu.utils;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RsaUtil {
    

	/**默认编码*/
	public final static String DEFAULT_CHARSET = "UTF-8";

    /** 
     * RSA最大加密明文大小 
     */  
    private static final int MAX_ENCRYPT_BLOCK = 117;  
      
    /** 
     * RSA最大解密密文大小 
     */  
    private static final int MAX_DECRYPT_BLOCK = 128; 
    
    /**
     * BASE64解密
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception{
        return (new BASE64Decoder()).decodeBuffer(key);
    }
    
    /**
     * BASE64加密
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key)throws Exception{
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    
    
//    public static final String KEY_ALGORTHM="RSA";
    public static final String KEY_ALGORTHM="RSA";
    public static final String SIGNATURE_ALGORITHM="MD5withRSA";
    
    public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
    public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥




    /**
     * 初始化密钥
     * @return
     * @throws Exception
     */
    public static Map<String,Object> initKey()throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //私钥
        RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
        Map<String,Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * 取得公钥，并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
        Key key = (Key) keyMap.get(PUBLIC_KEY);  
        return encryptBASE64(key.getEncoded());     
    }

    /**
     * 取得私钥，并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
        Key key = (Key) keyMap.get(PRIVATE_KEY);  
        return encryptBASE64(key.getEncoded());     
    }

    /**
     * 用私钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{
        //解密密钥
        byte[] keyBytes = decryptBASE64(key);
        //取私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        
        int inputLen = data.length;  
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        int offSet = 0;  
        byte[] cache;  
        int i = 0;  
        // 对数据分段加密  
        while (inputLen - offSet > 0) {  
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  
            } else {  
                cache = cipher.doFinal(data, offSet, inputLen - offSet);  
            }  
            out.write(cache, 0, cache.length);  
            i++;  
            offSet = i * MAX_ENCRYPT_BLOCK;  
        }  
        byte[] encryptedData = out.toByteArray();  
        out.close();  
        return encryptedData;
    }
    

    /**
     * 用私钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static String encryptByPrivateKey(String data,String key)throws Exception{
    	
    	return encryptBASE64(encryptByPrivateKey(data.getBytes(DEFAULT_CHARSET), key));
    }
    
    /**
     * 用私钥解密
     * @param data base64
     * @param key
     * @return String
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data,String key)throws Exception{
    	
    	return new String(decryptByPrivateKey(decryptBASE64(data), key),DEFAULT_CHARSET);
    }

    /**
     * 用私钥解密 * @param data 	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
        //对私钥解密
        byte[] keyBytes = decryptBASE64(key);
        
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        
        int inputLen = data.length;  
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        int offSet = 0;  
        byte[] cache;  
        int i = 0;  
        // 对数据分段解密  
        while (inputLen - offSet > 0) {  
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {  
                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);  
            } else {  
                cache = cipher.doFinal(data, offSet, inputLen - offSet);  
            }  
            out.write(cache, 0, cache.length);  
            i++;  
            offSet = i * MAX_DECRYPT_BLOCK;  
        }  
        byte[] decryptedData = out.toByteArray();  
        out.close();  
        return decryptedData; 
    }

    /**
     * 用公钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
        //对公钥解密
        byte[] keyBytes = decryptBASE64(key);
        //取公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        int inputLen = data.length;  
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        int offSet = 0;  
        byte[] cache;  
        int i = 0;  
        // 对数据分段加密  
        while (inputLen - offSet > 0) {  
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  
            } else {  
                cache = cipher.doFinal(data, offSet, inputLen - offSet);  
            }  
            out.write(cache, 0, cache.length);  
            i++;  
            offSet = i * MAX_ENCRYPT_BLOCK;  
        }  
        byte[] encryptedData = out.toByteArray();  
        out.close();  
        return encryptedData; 
    }

    /**
     * 用公钥解密
     * @param data	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
        //对私钥解密
        byte[] keyBytes = decryptBASE64(key);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        
        //对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        
        int inputLen = data.length;  
        ByteArrayOutputStream out = new ByteArrayOutputStream();  
        int offSet = 0;  
        byte[] cache;  
        int i = 0;  
        // 对数据分段解密  
        while (inputLen - offSet > 0) {  
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {  
                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);  
            } else {  
                cache = cipher.doFinal(data, offSet, inputLen - offSet);  
            }  
            out.write(cache, 0, cache.length);  
            i++;  
            offSet = i * MAX_DECRYPT_BLOCK;  
        }  
        byte[] decryptedData = out.toByteArray();  
        out.close();  
        return decryptedData;
    }

    /**
     * 用公钥加密
     * @param data	加密数据
     * @param key	密钥
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String data,String key)throws Exception{
    	
    	return encryptBASE64(encryptByPublicKey(data.getBytes(DEFAULT_CHARSET), key));
    }
    
    /**
     * 用公钥解密
     * @param data base64
     * @param key
     * @return String
     * @throws Exception
     */
    public static String decryptByPublicKey(String data,String key)throws Exception{
    	
    	return new String(decryptByPublicKey(decryptBASE64(data), key),DEFAULT_CHARSET);
    }
    
    public static void main(String[] args) throws Exception {
//    	Map<String,Object> keyMap = initKey();
//		String publicKey = getPublicKey(keyMap);
//		String privateKey = getPrivateKey(keyMap);
		String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4sNGKztDacMf/j73imuuXYxM0cTEMBQ7zH/K5xJIw6uQP7T0a0kUXvhEdQQsNpr5tQgsTmNivIIF9PNRw03qoTOVMG4/9uQC0mqOKKVfj0PbrEyIthJqlyEDOdHc1Aw2IOaxCncyrAbrMTHy7cpO+RXPH+T1Qge6280aLapxNhwIDAQAB";
		String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALiw0YrO0Npwx/+PveKa65djEzRxMQwFDvMf8rnEkjDq5A/tPRrSRRe+ER1BCw2mvm1CCxOY2K8ggX081HDTeqhM5Uwbj/25ALSao4opV+PQ9usTIi2EmqXIQM50dzUDDYg5rEKdzKsBusxMfLtyk75Fc8f5PVCB7rbzRotqnE2HAgMBAAECgYA4uRWiLCK49Cp4swz+q9XviN49HQaTSnps8UL7CwRbQckJmzNJKYtO33EiKvfaGXwi0kXUnvztzG34qNYWUN06jFAK+dhXMTb04/7urLQuJUMD5vRIrALkVd88btvDL9Fw3zrfVtnCRHsPSemio7ZfBUS3+vVV78S3VN31bt3OAQJBAPyxZQWlze0fk5xzVlenYiTtwMgvn9cYJCit1TE0glVNsQX5Qbhl8LNJ5QXv8GUwIzQ5v+J5pNUls5hJjjRIA2kCQQC7G5gAtXe2iSPn9VuOf7uMepmuwrx6fQHrOtR0MwCsrEvMLE5oInCppFci0wswEpQ0LkODq3Fo4pBB5AgJuNtvAkByTJtxboozE/Fk9xa7F09hfNmSs1gNpzHT5K1mUGYTx8ym8xQzIIk7z9T0Vo/adWe3G9gbzQIuF5ug6sSUCW7hAkEAotfbLRLCw90LoP/L1XOZ+SNiydS2USynFOE4soEJHz89IM+W1c7TmvFq3OYsoIQq9Fcnb1sw8wXsY0xhKoT2hQJBANOY4vBLFvUYo+SpZ8f5db0g2YP0UnjfEcZWRze3qYVPwOX1J6D6XJyzfos8Z7L2LQnEezIY5TF2DqEPOfRM8r8=";
		System.out.println("公钥:"+publicKey);
		System.out.println("公钥长度:"+publicKey.length());
		System.out.println("私钥:"+privateKey);
		System.out.println("私钥长度:"+privateKey.length());
		Map<String, String> map=new HashMap<>();
//		map.put("id", "140202021029");
//		map.put("pwd", "07caee910eb1c37e5d89ef1f6d9f82f1");
//		map.put("token", "04bb9fd2247741c5ecb6b6507d3e18c0");
//		String s = "{\"id\":\"130201031035\",\"pwd\":\"abcdefghijklmnopqrstuvwxyz\",\"token\":\"ZjKwUnMV93DlXclpx7dq\"}";
    // 	String s="{\"id\":\"140202021029\",\"pwd\":\"07caee910eb1c37e5d89ef1f6d9f82f1\",\"token\":\"04bb9fd2247741c5ecb6b6507d3e18c0\"}";
//		String s="aK+TCIqIgvPptGsPn/BHQwN+W1bvBJHBBV9rude/F1Pn3ds7x1Hzn/zjixlO+/W8mOETRqfvFU8yLblfvSLaXZMFV01dSP871ttDHneHf22lq/QzDas70JlO6fRBGhO77YkC2iN2zKzk1zN0CAePNCJmrt8wRkRGZPaXLLua0eU=";
//		String s=JsonUtil.toJson(map);
		String s="{\"id\":\"140202021029\",\"pwd\":\"KMx4i/u5DqWbKJxby6u7rsfARXzNklzpjEADGYXY9/VLpEuRRPxly7U/ftzoqPseCyp23J+yI5Tk\",\"token\":\"ywcXugEETZggzfi+f2E=\"}";
//		s = encryptByPublicKey(s, publicKey);
//		System.out.println("密文："+s);
//		String s="RpbblmCIULc1n1ZG11vWfNYMrM7/gMVkLC4qML41H5/n7PNocRJHDeAz2qbKJj+j4OAqP3A4R8MnbREeATdhDhEZt3Yy56gihBUp6UZmmq4ylJUxmpgS9D6zJVAwThpUmbFaHUi6KxAohZUYALV3NOhna4z8IOElPBYDaYZ5MpM=";
		//s = decryptByPrivateKey(s, privateKey);
     	String s1 = encryptByPublicKey(s, publicKey);
		System.out.println("明文："+s1);
	    System.out.println(decryptByPublicKey(s1,publicKey));
//		
	    
//		if(true)return;
//     	String s="1";
		
//		byte[] encMsg = encryptByPublicKey(s.getBytes(), publicKey);
//		String encMsgStr = encryptBASE64(encMsg);
//		System.out.println(encMsgStr);
//		System.out.println(new String(decryptByPrivateKey(decryptBASE64(encMsgStr), privateKey)));
	}
}